package com.example.tanlee.ocrgraduation.util;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.widget.ImageView;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 图片类型转换工具
 *
 * @author tanlee
 *
 */
public class ImageUtil {
	static MyLog log = MyLog.tanliLog();

	/**
	 * 以最省内存的方式读取本地资源的图片
	 *
	 * @param context
	 * @param resId
	 * @return
	 */
	public static Bitmap readBitMap(Context context, int resId) {
		Options opt = new Options();
		opt.inPreferredConfig = Config.RGB_565;
		opt.inPurgeable = true;
		opt.inInputShareable = true;
		// 获取资源图片
		InputStream is = context.getResources().openRawResource(resId);
		return BitmapFactory.decodeStream(is, null, opt);
	}

	/**
	 * 将Bitmap转为二进制数组
	 *
	 * @param bitmap
	 * @return
	 */
	public static byte[] bitmapToByte(Bitmap bitmap) {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		bitmap.compress(CompressFormat.JPEG, 100, out);
		try {
			out.flush();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return out.toByteArray();
	}

	/**
	 * 将Bitmap转为Drawable
	 *
	 * @param bitmap
	 * @return
	 */
	public static Drawable bitmapToDrawable(Bitmap bitmap) {
		Drawable drawable = new BitmapDrawable(bitmap);
		return drawable;
	}

	/**
	 * 将Drawable转为Bitmap类型
	 *
	 * @param drawable
	 * @return
	 */
	public static Bitmap drawableToBitmap(Drawable drawable) {
		int width = drawable.getIntrinsicWidth();
		int height = drawable.getIntrinsicHeight();
		Bitmap bitmap = Bitmap.createBitmap(width, height, drawable
				.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888
				: Config.RGB_565);
		Canvas canvas = new Canvas(bitmap);
		drawable.setBounds(0, 0, width, height);
		drawable.draw(canvas);
		return bitmap;
	}

	/**
	 * 将Drawable转为Byte[]类型
	 *
	 * @param drawable
	 * @return
	 */
	public static byte[] drawableToByte(Drawable drawable) {

		if (drawable != null) {
			Bitmap bitmap = Bitmap
					.createBitmap(
							drawable.getIntrinsicWidth(),
							drawable.getIntrinsicHeight(),
							drawable.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888
									: Config.RGB_565);
			Canvas canvas = new Canvas(bitmap);
			drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
					drawable.getIntrinsicHeight());
			drawable.draw(canvas);
			int size = bitmap.getWidth() * bitmap.getHeight() * 4;
			// 创建一个字节数组输出流,流的大小为size
			ByteArrayOutputStream baos = new ByteArrayOutputStream(size);
			// 设置位图的压缩格式，质量为100%，并放入字节数组输出流中
			bitmap.compress(CompressFormat.PNG, 100, baos);
			// 将字节数组输出流转化为字节数组byte[]
			byte[] imagedata = baos.toByteArray();
			return imagedata;
		}// www.sctarena.com
		return null;
	}

	/**
	 * 将Byte[]转为Bitmap类型
	 *
	 * @param temp
	 * @return
	 */
	public static Bitmap byteToBitmap(byte[] temp) {
		if (temp != null) {
			Bitmap bitmap = BitmapFactory.decodeByteArray(temp, 0, temp.length);
			return bitmap;
		} else {
			return null;
		}
	}

	/**
	 * 将Byte[]转为Drawable类型
	 *
	 * @return
	 */
	public static Drawable byteToDrawable(byte[] img) {
		Bitmap bitmap;
		if (img != null) {
			bitmap = BitmapFactory.decodeByteArray(img, 0, img.length);
			Drawable drawable = new BitmapDrawable(bitmap);
			return drawable;
		}
		return null;

	}

	/**
	 * 将二进制保存到英语单词卡片文件夹里，生成.jpg文件,并保存在sd卡里。
	 *
	 * @param bytes
	 * @param fileName
	 */
	public static void byteToImageFile(byte[] bytes, String fileName) {
		Bitmap bitmap = byteToBitmap(bytes);
		String path = SDCardUtil.getImagePath() + "/" + fileName;
		File imgFile = new File(path);
		if (imgFile.exists()) {
			imgFile.delete();
		}
		try {
			imgFile.createNewFile();
			FileOutputStream fos = new FileOutputStream(imgFile);
			bitmap.compress(CompressFormat.JPEG, 50, fos);
			fos.flush();
			fos.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 将二进制保存到英语单词卡片文件夹里，生成.jpg文件,并保存在sd卡里。
	 *
	 * @param fileName
	 */
	public static void bitmapToImageFile(Bitmap bitmap, String fileName) {
		String path = SDCardUtil.getImagePath() + "/" + fileName;
		File imgFile = new File(path);
		if (imgFile.exists()) {
			imgFile.delete();
		}
		try {
			imgFile.createNewFile();
			FileOutputStream fos = new FileOutputStream(imgFile);
			bitmap.compress(CompressFormat.JPEG, 85, fos);
			fos.flush();
			fos.close();
			bitmap = null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 将图片文件转为Bitmap对象
	 *
	 * @param file
	 * @return
	 */
	public static Bitmap fileToBitmap(File file) {
		Bitmap bitmap = null;
		if (file.exists()) {
			try {
				bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}
		return bitmap;
	}

	/**
	 *
	 * @author Hedq
	 * @version 创建时间：2014-11-13 下午3:01:45
	 * @param path
	 *            图片路径
	 * @param targetLength
	 *            目标长度
	 * @param isResizeWidth
	 *            是否以宽度为标准，true是以宽度，false是以高度
	 * @return
	 */
	public static Bitmap getResizedBitmap(String path, int targetLength,
			boolean isResizeWidth) {
		// 首先不加载图片,仅获取图片尺寸
		Options options = new Options();
		if (targetLength > 0) {
			// 当inJustDecodeBounds设为true时,不会加载图片仅获取图片尺寸信息
			options.inJustDecodeBounds = true;
			// 此时仅会将图片信息会保存至options对象内,decode方法不会返回bitmap对象
			BitmapFactory.decodeFile(path, options);

			int originWidth = options.outWidth;
			if (!isResizeWidth)
				originWidth = Math.max(originWidth, options.outHeight);
			// 计算压缩比例,如inSampleSize=4时,图片会压缩成原图的1/4
			options.inSampleSize = sampleSize(originWidth, targetLength);
			// 当inJustDecodeBounds设为false时,BitmapFactory.decode...就会返回图片对象了
			options.inJustDecodeBounds = false;
		}
		Bitmap bm = null;
		try {
			bm = BitmapFactory.decodeFile(path, options);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bm;

	}

	/**
	 * 获取合适的sampleSize. 这里就简单实现都是2的倍数啦.
	 *
	 * @param origin
	 *            原长度
	 * @param target
	 *            目标长度
	 * @return
	 */
	public static int sampleSize(int origin, int target) {
		int inSampleSize = 1;
		if (origin > target) {
			// 压缩比例值每次循环两倍增加,
			// 直到原图宽高值的一半除以压缩值后都~大于所需宽高值为止
			while (origin / inSampleSize >= target) {
				inSampleSize *= 2;
			}
		}
		return inSampleSize;
	}

	/**
	 * 调整图片大小
	 *
	 * @param bm
	 * @param winWidth
	 * @param winHeight
	 * @return
	 */
	public static Bitmap scaleImg(Bitmap bm, Context context, int winWidth,
			int winHeight) {
		int width = bm.getWidth();
		int height = bm.getHeight();

		int newWidth = winWidth - ScreenUtil.dip2px(20);
		// 计算缩放比例
		float scale = ((float) newWidth) / width;

		// 取得想要缩放的matrix参数
		Matrix matrix = new Matrix();
		matrix.postScale(scale, scale); // 宽、高缩放比例一样
		// 得到新的图片
		Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix,
				true);
		return newbm;
	}

	public static Bitmap fastblur(Bitmap sentBitmap, int radius) {

		// Stack Blur v1.0 from
		// http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
		//
		// Java Author: Mario Klingemann <mario at quasimondo.com>
		// http://incubator.quasimondo.com
		// created Feburary 29, 2004
		// Android port : Yahel Bouaziz <yahel at kayenko.com>
		// http://www.kayenko.com
		// ported april 5th, 2012

		// This is a compromise between Gaussian Blur and Box blur
		// It creates much better looking blurs than Box Blur, but is
		// 7x faster than my Gaussian Blur implementation.
		//
		// I called it Stack Blur because this describes best how this
		// filter works internally: it creates a kind of moving stack
		// of colors whilst scanning through the image. Thereby it
		// just has to add one new block of color to the right side
		// of the stack and remove the leftmost color. The remaining
		// colors on the topmost layer of the stack are either added on
		// or reduced by one, depending on if they are on the right or
		// on the left side of the stack.
		//
		// If you are using this algorithm in your code please add
		// the following line:
		//
		// Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>

		Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);

		if (radius < 1) {
			return (null);
		}

		int w = bitmap.getWidth();
		int h = bitmap.getHeight();

		int[] pix = new int[w * h];
		bitmap.getPixels(pix, 0, w, 0, 0, w, h);

		int wm = w - 1;
		int hm = h - 1;
		int wh = w * h;
		int div = radius + radius + 1;

		int r[] = new int[wh];
		int g[] = new int[wh];
		int b[] = new int[wh];
		int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
		int vmin[] = new int[Math.max(w, h)];

		int divsum = (div + 1) >> 1;
		divsum *= divsum;
		int dv[] = new int[256 * divsum];
		for (i = 0; i < 256 * divsum; i++) {
			dv[i] = (i / divsum);
		}

		yw = yi = 0;

		int[][] stack = new int[div][3];
		int stackpointer;
		int stackstart;
		int[] sir;
		int rbs;
		int r1 = radius + 1;
		int routsum, goutsum, boutsum;
		int rinsum, ginsum, binsum;

		for (y = 0; y < h; y++) {
			rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
			for (i = -radius; i <= radius; i++) {
				p = pix[yi + Math.min(wm, Math.max(i, 0))];
				sir = stack[i + radius];
				sir[0] = (p & 0xff0000) >> 16;
				sir[1] = (p & 0x00ff00) >> 8;
				sir[2] = (p & 0x0000ff);
				rbs = r1 - Math.abs(i);
				rsum += sir[0] * rbs;
				gsum += sir[1] * rbs;
				bsum += sir[2] * rbs;
				if (i > 0) {
					rinsum += sir[0];
					ginsum += sir[1];
					binsum += sir[2];
				} else {
					routsum += sir[0];
					goutsum += sir[1];
					boutsum += sir[2];
				}
			}
			stackpointer = radius;

			for (x = 0; x < w; x++) {

				r[yi] = dv[rsum];
				g[yi] = dv[gsum];
				b[yi] = dv[bsum];

				rsum -= routsum;
				gsum -= goutsum;
				bsum -= boutsum;

				stackstart = stackpointer - radius + div;
				sir = stack[stackstart % div];

				routsum -= sir[0];
				goutsum -= sir[1];
				boutsum -= sir[2];

				if (y == 0) {
					vmin[x] = Math.min(x + radius + 1, wm);
				}
				p = pix[yw + vmin[x]];

				sir[0] = (p & 0xff0000) >> 16;
				sir[1] = (p & 0x00ff00) >> 8;
				sir[2] = (p & 0x0000ff);

				rinsum += sir[0];
				ginsum += sir[1];
				binsum += sir[2];

				rsum += rinsum;
				gsum += ginsum;
				bsum += binsum;

				stackpointer = (stackpointer + 1) % div;
				sir = stack[(stackpointer) % div];

				routsum += sir[0];
				goutsum += sir[1];
				boutsum += sir[2];

				rinsum -= sir[0];
				ginsum -= sir[1];
				binsum -= sir[2];

				yi++;
			}
			yw += w;
		}
		for (x = 0; x < w; x++) {
			rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
			yp = -radius * w;
			for (i = -radius; i <= radius; i++) {
				yi = Math.max(0, yp) + x;

				sir = stack[i + radius];

				sir[0] = r[yi];
				sir[1] = g[yi];
				sir[2] = b[yi];

				rbs = r1 - Math.abs(i);

				rsum += r[yi] * rbs;
				gsum += g[yi] * rbs;
				bsum += b[yi] * rbs;

				if (i > 0) {
					rinsum += sir[0];
					ginsum += sir[1];
					binsum += sir[2];
				} else {
					routsum += sir[0];
					goutsum += sir[1];
					boutsum += sir[2];
				}

				if (i < hm) {
					yp += w;
				}
			}
			yi = x;
			stackpointer = radius;
			for (y = 0; y < h; y++) {
				// Preserve alpha channel: ( 0xff000000 & pix[yi] )
				pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16)
						| (dv[gsum] << 8) | dv[bsum];

				rsum -= routsum;
				gsum -= goutsum;
				bsum -= boutsum;

				stackstart = stackpointer - radius + div;
				sir = stack[stackstart % div];

				routsum -= sir[0];
				goutsum -= sir[1];
				boutsum -= sir[2];

				if (x == 0) {
					vmin[y] = Math.min(y + r1, hm) * w;
				}
				p = x + vmin[y];

				sir[0] = r[p];
				sir[1] = g[p];
				sir[2] = b[p];

				rinsum += sir[0];
				ginsum += sir[1];
				binsum += sir[2];

				rsum += rinsum;
				gsum += ginsum;
				bsum += binsum;

				stackpointer = (stackpointer + 1) % div;
				sir = stack[stackpointer];

				routsum += sir[0];
				goutsum += sir[1];
				boutsum += sir[2];

				rinsum -= sir[0];
				ginsum -= sir[1];
				binsum -= sir[2];

				yi += w;
			}
		}
		bitmap.setPixels(pix, 0, w, 0, 0, w, h);

		return (bitmap);
	}

	/**
	 * 将大图片文件保存成一张临时的小图片文件，起名为temp.jpg
	 *
	 * @author Hedq
	 * @version 创建时间：2014-11-13 下午3:28:23
	 * @param path
	 * @param imgNameString
	 * @return
	 */
	public static String getResizeFile(final String path,
			final String imgNameString) {
		final String fileName =imgNameString+ ".jpg";
		bitmapToImageFile(getResizedBitmap(path, 1080, false), fileName);
		return (SDCardUtil.getImagePath() + "/" + fileName);
	}

	/**
	 * 针对课程列表和众筹列表，把缩略图的url后缀加上-1，取得对应大图的url
	 *
	 * @author Hedq
	 * @version 创建时间：2014-12-1 下午7:03:04
	 * @param url
	 * @return
	 */
	public static String getBigImgUrl(String url) {
		String bigUrl = url;
		if (url.contains("jpg")) {
			bigUrl = url.replace(".jpg", "-1.jpg");
		} else if (url.contains(".png")) {
			bigUrl = url.replace(".png", "-1.png");
		}
		return bigUrl;
	}

	/**
	 * 手动释放控件的图片资源
	 *
	 * @author Hedq
	 * @version 创建时间：2014-12-4 下午6:58:46
	 * @param imageView
	 */
	public static void releaseImageView(ImageView imageView) {
		if (imageView != null) {
			Drawable d = imageView.getDrawable();
			if (d != null)
				d.setCallback(null);
			Drawable bg = imageView.getBackground();
			if (bg != null)
				bg.setCallback(null);
			imageView.setImageDrawable(null);
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
				imageView.setBackground(null);
			} else {
				imageView.setBackgroundDrawable(null);
			}
		}
	}

	public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {

        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final Paint paint = new Paint();
        //保证是方形，并且从中心画
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int w;
        int deltaX = 0;
        int deltaY = 0;
        if (width <= height) {
            w = width;
            deltaY = height - w;
        } else {
            w = height;
            deltaX = width - w;
        }
        final Rect rect = new Rect(deltaX, deltaY, w, w);
        final RectF rectF = new RectF(rect);

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        //圆形，所有只用一个

        int radius = (int) (Math.sqrt(w * w * 2.0d) / 2);
        canvas.drawRoundRect(rectF, radius, radius, paint);

        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        return output;
    }

	/**
	 * 根据api版本，设置图片
	 * @param resources getResource()
	 * @param img 控件名
	 * @param drawable R.drawable.XX 资源文件
	 */
	public static void setImage(Resources resources,ImageView img, int drawable){
		int currentapiVersion = Build.VERSION.SDK_INT;
		//释放对象的引用
		ImageView view = null;
		if(img != null){
			view = img;
			if(currentapiVersion > 21){
				view.setImageDrawable(resources.getDrawable(drawable, null));
			}
			else{
				view.setImageDrawable(resources.getDrawable(drawable));
			}
		}
	}

	/**
	 * 将bitmap转成byte
	 * @param bitmap
	 * @return
	 */
	public static byte[] bitmapToBytes(Bitmap bitmap){
		if (bitmap == null) {
			return null;
		}
		final ByteArrayOutputStream os = new ByteArrayOutputStream();
		// 将Bitmap压缩成PNG编码，质量为100%存储
		bitmap.compress(CompressFormat.PNG, 100, os);//除了PNG还有很多常见格式，如jpeg等。
		return os.toByteArray();
	}

	/**
	 * 如果少了http://添加上
	 * @param imgUrl
	 * @return
	 */
	public static String addHttpHead(String imgUrl){
		if (imgUrl == null){
			return null;
		}
		else{
			String tempString = imgUrl.substring(0,4);
			if (!tempString.equals("http")){
				imgUrl = "http://" + imgUrl;
			}
			return imgUrl;
		}
	}
}
